﻿#include "Slider.h"
#include <QMouseEvent>
#include <QDateTime>
#include <QStyle>
#include <QDebug>

namespace GeneralUI 
{
	Slider::Slider(QWidget *parent)
		: QSlider(parent)
	{
		init();
	}

	Slider::Slider(Qt::Orientation orientation, QWidget *parent)
		:QSlider(orientation, parent)
	{
		init();
	}

	Slider::~Slider()
	{

	}

	void Slider::setDecimals(int decs)
	{
		if (decs < 0)
		{
			return;
		}
		m_decimals = decs;
		initForm(pow(10, m_decimals));

		notifyValueChanged(false);
	}

	int Slider::getDecimals()
	{
		return m_decimals;
	}

	void Slider::setValue(double value)
	{
		__super::setValue(value * m_multiple);
	}

	double Slider::value()
	{
		return __super::value()*1.0 / m_multiple;
	}

	void Slider::setRange(double min, double max)
	{
		int curMin = __super::minimum();
		int curMax = __super::maximum();

		int newMin = min * m_multiple;
		int newMax = max * m_multiple;

		if (curMax != newMax || curMin != newMin)
		{
			__super::setRange(newMin, newMax);
		}
	}

	void Slider::setMinimum(int min)
	{
		int curMin = __super::minimum();
		int newMin = min * m_multiple;

		if (curMin != newMin)
		{
			__super::setRange(newMin, __super::maximum());
		}
	}

	void Slider::setMaximum(int max)
	{
		int curMax = __super::maximum();
		int newMax = max * m_multiple;
		if (curMax != newMax)
		{
			__super::setRange(__super::minimum(), newMax);
		}
	}

	double Slider::maximum()
	{
		return __super::maximum() * 1.0 / m_multiple;
	}

	double Slider::minimum()
	{
		return __super::minimum() * 1.0 / m_multiple;
	}

	void Slider::setSingleStep(double singleStep)
	{
		__super::setSingleStep(singleStep * m_multiple);
	}

	double Slider::singleStep() const
	{
		return __super::singleStep()*1.0 / m_multiple;
	}

	bool Slider::hasFocus()
	{
		return m_hasMouseFocus || __super::hasFocus();
	}

	void Slider::mousePressEvent(QMouseEvent *event)
	{
		__super::mousePressEvent(event);

		if (event->button() != Qt::LeftButton)
		{
			return;
		}
		setSliderDown(true);

		int start = orientation() == Qt::Vertical ? (height() - event->y()) : event->x();
		int size = orientation() == Qt::Horizontal ? width() : height();
		int curValue = QStyle::sliderValueFromPosition(__super::minimum(), __super::maximum(), start, size - 1, false);
		__super::setValue(curValue);

		notifyValueChanged(false);
	}

	void Slider::mouseMoveEvent(QMouseEvent * event)
	{
		__super::mouseMoveEvent(event);

		int start = orientation() == Qt::Vertical ? (height() - event->y()) : event->x();
		int size = orientation() == Qt::Horizontal ? width() : height();
		int curValue = QStyle::sliderValueFromPosition(__super::minimum(), __super::maximum(), start, size - 1, false);
		__super::setValue(curValue);

		notifyValueChanged(false);
	}

	void Slider::mouseReleaseEvent(QMouseEvent *event)
	{
		notifyValueChanged(true);

		__super::mouseReleaseEvent(event);
		setSliderDown(false);
	}

	void Slider::wheelEvent(QWheelEvent * event)
	{
		double delta = event->delta();
		Qt::KeyboardModifiers modifiers = event->modifiers();
		if (event->inverted())
		{
			delta = -delta;
		}

		double offset = delta / 120;
		int stepsToScroll = 0;

		if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::ShiftModifier))
		{
			stepsToScroll = qBound(-pageStep(), int(offset * pageStep()), pageStep());
		}
		else
		{
			stepsToScroll = int(offset * __super::singleStep());
		}

		stepsToScroll = invertedControls() ? -stepsToScroll : stepsToScroll;
		int value = __super::value() + stepsToScroll;
		value = qBound(__super::minimum(), value, __super::maximum());
		__super::setValue(value);

		notifyValueChanged(false);
	}

	void Slider::enterEvent(QEvent * event)
	{
		__super::enterEvent(event);
		m_hasMouseFocus = true;
	}

	void Slider::leaveEvent(QEvent * event)
	{
		__super::leaveEvent(event);
		m_hasMouseFocus = false;
	}

	void Slider::init()
	{
		m_hasMouseFocus = false;
		m_decimals = 0;
		m_multiple = 1;
		m_lastOrignalValue = 0;
		setPageStep(0);
	}

	void Slider::initForm(double newMultiple)
	{
		double multiple = newMultiple / m_multiple;

		if (multiple > 1)
		{
			int curMin = __super::minimum()*multiple;
			int curMax = __super::maximum()*multiple;
			__super::setRange(curMin, curMax);

			int value = __super::value()*multiple;
			__super::setValue(value);
		}
		else
		{
			int value = __super::value()*multiple;
			__super::setValue(value);

			int curMin = __super::minimum()*multiple;
			int curMax = __super::maximum()*multiple;
			__super::setRange(curMin, curMax);
		}

		int singleStep = __super::singleStep()*multiple;
		__super::setSingleStep(singleStep);
		update();

		m_multiple = newMultiple;
	}

	void Slider::notifyValueChanged(const bool isLast)
	{
		int orignalValue = __super::value();
		if (hasTracking() && (m_lastOrignalValue != orignalValue))
		{
			m_lastOrignalValue = orignalValue;
			double curentValue = QString::number(__super::value() * 1.0 / m_multiple, 'f', m_decimals).toDouble();
			emit signalValueChanged(curentValue, isLast);
		}
	}

}
